import {useUserStore} from "@/store/modules/user";
import {layer} from '@layui/layui-vue';
import router from '../router'
import {createAlova} from 'alova';
import adapterFetch from 'alova/fetch';
import VueHook from 'alova/vue';

type TAxiosOption = {
    timeout: number;
    baseURL: string;
}

const config: TAxiosOption = {
    timeout: 5000,
    baseURL: "http://localhost:8080"
}

class Http {
    service;

    constructor(config: TAxiosOption) {

        this.service = createAlova({
            ...config,
            requestAdapter: adapterFetch(),
            statesHook: VueHook,
            beforeRequest(method) {
                // 假设我们需要添加token到请求头
                const userInfoStore = useUserStore();
                if (userInfoStore.token) {
                    (method.config.headers).token = userInfoStore.token as string
                } else {
                    if (router.currentRoute.value.path !== '/login') {
                        router.push('/login');
                    }
                }
            },
            // 使用 responded 对象分别指定请求成功的拦截器和请求失败的拦截器
            responded: {
                // 请求成功的拦截器
                // 当使用 `alova/fetch` 请求适配器时，第一个参数接收Response对象
                // 第二个参数为当前请求的method实例，你可以用它同步请求前后的配置信息
                onSuccess: async (response, method) => {
                    // if (response.status >= 400) {
                    //     throw new Error(response.statusText);
                    // }
                    const json = await response.json();
                    // if (json.code !== 200) {
                    //     // 抛出错误或返回reject状态的Promise实例时，此请求将抛出错误
                    //     throw new Error(json.message);
                    // }

                    // 解析的响应数据将传给method实例的transform钩子函数，这些函数将在后续讲解
                    return json.data;
                },
                // 请求失败的拦截器
                // 请求错误时将会进入该拦截器。
                // 第二个参数为当前请求的method实例，你可以用它同步请求前后的配置信息
                onError: (error, method) => {
                    layer.msg(error.message, {icon: 2, time: 1000})
                },

                // 请求完成的拦截器
                // 当你需要在请求不论是成功、失败、还是命中缓存都需要执行的逻辑时，可以在创建alova实例时指定全局的`onComplete`拦截器，例如关闭请求 loading 状态。
                // 接收当前请求的method实例
                onComplete: async method => {
                    // 处理请求完成逻辑
                }
            }
        });
        // /* 请求拦截 */
        // this.service.interceptors.request.use((config: InternalAxiosRequestConfig) => {
        //     const userInfoStore = useUserStore();
        //     if (userInfoStore.token) {
        //         (config.headers as AxiosRequestHeaders).token = userInfoStore.token as string
        //     } else {
        //         if (router.currentRoute.value.path !== '/login') {
        //             router.push('/login');
        //         }
        //     }
        //     return config
        // }, error => {
        //     return Promise.reject(error);
        // })
        //
        // /* 响应拦截 */
        // this.service.interceptors.response.use((response: AxiosResponse<any>) => {
        //     switch (response.data.code) {
        //         case 200:
        //             return response.data;
        //         case 500:
        //             return response.data;
        //         case 99998:
        //             layer.confirm(
        //                 '会话超时, 请重新登录',
        //                 {
        //                     icon: 2, yes: function () {
        //                         router.push('/login');
        //                         layer.closeAll()
        //                     }
        //                 });
        //             return response.data;
        //         default:
        //             break;
        //     }
        // }, error => {
        //     return Promise.reject(error)
        // })
    }

    /* GET 方法 */
    get<T>(url: string, params?: object, _object = {}): Promise<any> {
        return this.service.Get(url, {params, ..._object})
    }

    /* POST 方法 */
    post<T>(url: string, params?: object, _object = {}): Promise<any> {
        return this.service.Post(url, params, _object)
    }

    /* PUT 方法 */
    put<T>(url: string, params?: object, _object = {}): Promise<any> {
        return this.service.Put(url, params, _object)
    }

    /* DELETE 方法 */
    delete<T>(url: string, params?: any, _object = {}): Promise<any> {
        return this.service.Delete(url, {params, ..._object})
    }
}

export default new Http(config)
